#include "Cache.hpp"
#include "CacheManager.hpp"

#include <vector>
#include <iostream>
#include <functional>
#include <unistd.h>
#include <memory>
using std::function;
using std::unique_ptr;
using std::bind;
using std::vector;
using std::endl;
using std::cout;

namespace ylw
{

size_t num = 3;//和cacheNum一样，配置文件
string filePath = "result.txt";//配置文件
size_t CacheManager::_cacheNum = 3;//配置文件
/* size_t CacheManager::_memorySize = 100; */


Cache initialGlobleCache(){
    Cache cache(0);
    cache.readFromFile(filePath);
    return cache;
}

vector<Cache> initial_list(){
    vector<Cache> tmp;
    size_t cnt = 1;
    for(size_t i = 0; i < num; ++i){
        Cache cache(cnt);
        cache.readFromFile(filePath);
        tmp.push_back(cache);
    }
    return tmp;
}

Cache CacheManager::_globlCache(initialGlobleCache());
vector<Cache> CacheManager::_cacheList(initial_list());

void CacheManager::initCache(){
    periodicUpdateCaches();
}

// 根据缓存号获取缓存
Cache & CacheManager::getCache(size_t idx){
    return _cacheList[idx];
}

//一段时间后，用全局cache更新全部线程cache
//首先读取所有线程的updateData，存储到全局cache中
//然后回写到各个线程
void CacheManager::periodicUpdateCaches(){
    //----------定时功能---------------------
    unique_ptr<ylw::Timer> timer(
            new ylw::Timer(updateProcess, 5, 5));

    unique_ptr<ylw::Thread> timerThread(new ylw::Thread(
            bind(&ylw::Timer::start, timer.get())));
    timerThread->start();


    ::sleep(600);
    timer->stop();
    timerThread->join();
}

void CacheManager::updateProcess(){
    size_t cnt = 0;
    for(size_t idx = 0; idx < _cacheNum; ++idx){
        /* Cache cache(getCache(idx)); */
        for(auto &elem : getCache(idx)._updateData){
            /* if(cnt <= _memorySize){ */
            if(cnt <= 100){
                _globlCache._hashMap.insert(make_pair(elem.first, elem.second));
                ++cnt;
            }else{
                goto WriteBackToCache;
            }
        }
    }
    _globlCache.writeToFile(filePath); 
    cout << endl << "Write back to disk cache success!" << endl << endl;

WriteBackToCache:
    //回写到线程cache
    cout << "--------------Update Message------------------" <<  endl;
    for(size_t idx = 0;  idx < _cacheNum; ++idx){
        getCache(idx).update(_globlCache);
        cout << "Cache number" << idx << ":" << "read finished" << endl;
    }
    cout << "-------Cache initialization finished----------" << endl << endl;
}

}//end of namespace ylw
